package com.mspbots.web.security;

import com.fasterxml.jackson.databind.JsonNode;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.relational.core.mapping.Table;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * com.mspbots.web.security.User
 *
 * @author Alex bob(https://github.com/vnobo)
 * @date Created by 2019/7/19
 */
@Data
@Table("users")
@NoArgsConstructor
public class User implements Serializable {

    @Id
    private Integer id;
    private String password;
    private Boolean enabled;
    private Integer tenantId;
    private String username, firstName, lastName, email;
    private LocalDateTime modifiedTime, lastLogin, createdTime;
    private Set<String> authorities;
    private Long managerUserId;
    private String timezoneFull;
    private String timezoneShort;
    private JsonNode removed;

    @Transient
    private String identifier;
    @Transient
    private String cwUid;

    public User(String username, String password, Set<String> roles, boolean enabled) {
        this(username, password, roles, enabled, 0, null, null, null, null);
    }

    @Builder
    User(String username, String password, Set<String> roles, boolean enabled, int tenantId,
         String firstName, String lastName, String email, String identifier) {
        Assert.isTrue(!StringUtils.isEmpty(username), () -> username + " cannot empty.");
        this.identifier = identifier;
        this.username = username.toLowerCase();
        this.password = password;
        this.authorities = roles;
        this.enabled = enabled;
        this.tenantId = tenantId;
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }

    public static User of(String username, String password, Set<String> roles, boolean enabled) {
        return new User(username, password, roles, enabled);
    }

    private static Set<String> sortAuthorities(Set<String> authorities) {
        Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
        // Ensure array iteration order is predictable (as per
        // UserDetails.getAuthorities() contract and SEC-717)
        List<String> sortedAuthorities = new ArrayList<>(authorities);
        return sortedAuthorities.parallelStream().sorted().map(role -> "ROLE_" + role).collect(Collectors.toSet());
    }
}
